var when = {
    pipeline : function(arrayOfFunctions, arg, firstIndex ) {
        if (!firstIndex) {
            firstIndex = 0;
        }
        if (firstIndex < arrayOfFunctions.length) {
            try {
                var firstOpReturns = arrayOfFunctions[firstIndex](arg);
                if (pipe in firstOpReturns) {
                    return firstOpReturns.pipe(function(result) {
                        return when.pipeline(arrayOfFunctions, result, ++firstIndex);
                    });
                } else {
                    return when.pipeline(arrayOfFunctions, result, ++firstIndex);
                }
            }
            catch (e) {
                return $.Deferred().reject(e).promise();
            }
        }
        return $.Deferred().resolve(arg).promise();
    },
    all : function(arrayOfDeferrends, firstIndex, results, finalPromise) {
        if (!firstIndex) {
            firstIndex = 0;
            results = [];
            finalPromise = $.Deferred();
        }

        if (firstIndex < arrayOfDeferrends.length) {
            $.when(arrayOfDeferrends[firstIndex])
            .then( function(result) {
                results.push({
                    success : result
                });
            })
            .fail(function(error){
                    results.push({
                        error : error
                    });
            })
            .always(function() {
                when.all(arrayOfDeferrends, ++firstIndex, results, finalPromise);
            });
        } else {
            finalPromise.resolve(results);
        }
        return finalPromise.promise();
    }
}

var debug = {
    assert : function(condition, message) {
        if (!condition) {
            var error = new Error(message);
            console.error(message+"\n"+error.stack);
            if (module) {
                //executes in a node env
                throw error;
            }
        }
    }
}


if (typeof window === 'undefined') {
    module.exports = {
        when    : when,
        debug   : debug
    };
}